import { io, Socket } from 'socket.io-client';
import { WS_URL, SOCKET_EVENTS } from '@/utils/constants';
import {
  SocketMessage,
  JoinRoomMessage,
  RoomJoinedMessage,
  OfferMessage,
  AnswerMessage,
  IceCandidateMessage,
  UserLeftMessage,
} from '@/types';

/**
 * Socket 连接管理类
 */
class SocketManager {
  private socket: Socket | null = null;
  private reconnectAttempts = 0;
  private maxReconnectAttempts = 5;
  private reconnectDelay = 1000;

  /**
   * 连接到服务器
   */
  connect(): Promise<Socket> {
    return new Promise((resolve, reject) => {
      if (this.socket?.connected) {
        resolve(this.socket);
        return;
      }

      this.socket = io(WS_URL, {
        transports: ['websocket', 'polling'],
        timeout: 10000,
        reconnection: true,
        reconnectionAttempts: this.maxReconnectAttempts,
        reconnectionDelay: this.reconnectDelay,
      });

      this.socket.on('connect', () => {
        console.log('Socket 连接成功:', this.socket!.id);
        this.reconnectAttempts = 0;
        resolve(this.socket!);
      });

      this.socket.on('connect_error', (error) => {
        console.error('Socket 连接错误:', error);
        this.reconnectAttempts++;
        if (this.reconnectAttempts >= this.maxReconnectAttempts) {
          reject(new Error('Socket 连接失败，请检查网络连接'));
        }
      });

      this.socket.on('disconnect', (reason) => {
        console.log('Socket 连接断开:', reason);
      });

      this.socket.on('reconnect', (attemptNumber) => {
        console.log('Socket 重连成功:', attemptNumber);
      });

      this.socket.on('reconnect_error', (error) => {
        console.error('Socket 重连失败:', error);
      });
    });
  }

  /**
   * 断开连接
   */
  disconnect(): void {
    if (this.socket) {
      this.socket.disconnect();
      this.socket = null;
    }
  }

  /**
   * 获取当前 socket 实例
   */
  getSocket(): Socket | null {
    return this.socket;
  }

  /**
   * 检查连接状态
   */
  isConnected(): boolean {
    return this.socket?.connected || false;
  }

  /**
   * 发送消息
   */
  emit(event: string, data: any): void {
    if (this.socket?.connected) {
      this.socket.emit(event, data);
    } else {
      console.error('Socket 未连接，无法发送消息');
    }
  }

  /**
   * 监听消息
   */
  on(event: string, callback: (data: any) => void): void {
    if (this.socket) {
      this.socket.on(event, callback);
    }
  }

  /**
   * 取消监听
   */
  off(event: string, callback?: (data: any) => void): void {
    if (this.socket) {
      this.socket.off(event, callback);
    }
  }

  /**
   * 加入房间
   */
  joinRoom(roomId: string, userId: string): void {
    const message: JoinRoomMessage = {
      type: SOCKET_EVENTS.JOIN_ROOM,
      data: { roomId, userId },
    };
    this.emit(SOCKET_EVENTS.JOIN_ROOM, message.data);
  }

  /**
   * 离开房间
   */
  leaveRoom(roomId: string, userId: string): void {
    this.emit(SOCKET_EVENTS.LEAVE_ROOM, { roomId, userId });
  }

  /**
   * 发送 WebRTC Offer
   */
  sendOffer(to: string, from: string, offer: RTCSessionDescriptionInit): void {
    const message: OfferMessage = {
      type: SOCKET_EVENTS.OFFER,
      data: { to, from, offer },
    };
    this.emit(SOCKET_EVENTS.OFFER, message.data);
  }

  /**
   * 发送 WebRTC Answer
   */
  sendAnswer(to: string, from: string, answer: RTCSessionDescriptionInit): void {
    const message: AnswerMessage = {
      type: SOCKET_EVENTS.ANSWER,
      data: { to, from, answer },
    };
    this.emit(SOCKET_EVENTS.ANSWER, message.data);
  }

  /**
   * 发送 ICE Candidate
   */
  sendIceCandidate(to: string, from: string, candidate: RTCIceCandidateInit): void {
    const message: IceCandidateMessage = {
      type: SOCKET_EVENTS.ICE_CANDIDATE,
      data: { to, from, candidate },
    };
    this.emit(SOCKET_EVENTS.ICE_CANDIDATE, message.data);
  }

  /**
   * 通知音频状态变化
   */
  toggleAudio(roomId: string, userId: string, enabled: boolean): void {
    this.emit(SOCKET_EVENTS.TOGGLE_AUDIO, {
      roomId,
      userId,
      enabled,
    });
  }

  /**
   * 通知视频状态变化
   */
  toggleVideo(roomId: string, userId: string, enabled: boolean): void {
    this.emit(SOCKET_EVENTS.TOGGLE_VIDEO, {
      roomId,
      userId,
      enabled,
    });
  }

  /**
   * 监听房间事件
   */
  onRoomJoined(callback: (data: RoomJoinedMessage['data']) => void): void {
    this.on(SOCKET_EVENTS.ROOM_JOINED, callback);
  }

  /**
   * 监听用户加入事件
   */
  onUserJoined(callback: (data: { userId: string; roomId: string }) => void): void {
    this.on(SOCKET_EVENTS.USER_JOINED, callback);
  }

  /**
   * 监听用户离开事件
   */
  onUserLeft(callback: (data: UserLeftMessage['data']) => void): void {
    this.on(SOCKET_EVENTS.USER_LEFT, callback);
  }

  /**
   * 监听 WebRTC Offer
   */
  onOffer(callback: (data: OfferMessage['data']) => void): void {
    this.on(SOCKET_EVENTS.OFFER, callback);
  }

  /**
   * 监听 WebRTC Answer
   */
  onAnswer(callback: (data: AnswerMessage['data']) => void): void {
    this.on(SOCKET_EVENTS.ANSWER, callback);
  }

  /**
   * 监听 ICE Candidate
   */
  onIceCandidate(callback: (data: IceCandidateMessage['data']) => void): void {
    this.on(SOCKET_EVENTS.ICE_CANDIDATE, callback);
  }

  /**
   * 监听房间满员事件
   */
  onRoomFull(callback: (data: { roomId: string }) => void): void {
    this.on(SOCKET_EVENTS.ROOM_FULL, callback);
  }

  /**
   * 监听房间不存在事件
   */
  onRoomNotFound(callback: (data: { roomId: string }) => void): void {
    this.on(SOCKET_EVENTS.ROOM_NOT_FOUND, callback);
  }

  /**
   * 监听音频状态变化
   */
  onAudioToggle(callback: (data: { userId: string; enabled: boolean }) => void): void {
    this.on(SOCKET_EVENTS.TOGGLE_AUDIO, callback);
  }

  /**
   * 监听视频状态变化
   */
  onVideoToggle(callback: (data: { userId: string; enabled: boolean }) => void): void {
    this.on(SOCKET_EVENTS.TOGGLE_VIDEO, callback);
  }

  /**
   * 清理所有事件监听器
   */
  removeAllListeners(): void {
    if (this.socket) {
      this.socket.removeAllListeners();
    }
  }
}

// 创建单例实例
export const socketManager = new SocketManager();

// 导出默认实例
export default socketManager;